home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / graphics / fpoly256.zip / VGAXLINE.ASM < prev    next >
Assembly Source File  |  1991-12-17  |  11KB  |  721 lines

  1.  
  2.     TITLE    VGALINE - Fast line drawing routine.
  3.     NAME    VGALINE
  4.  
  5.     COMMENT    $
  6.  
  7.     Name:        VGALINE
  8.  
  9.         Written and (c) by Dave Stampe 9/11/91
  10.         Not for commercial use, so get permission
  11.         before marketing code using this stuff!
  12.         For private PD use only.
  13.  
  14.         $
  15.  
  16.  
  17.  
  18.     COMMENT    $
  19.  
  20.     Name:        VGALINE
  21.  
  22.     Function:    Draw a line in VGA 200 line 256 color X mode
  23.  
  24.     Caller:        C:
  25.  
  26.             void vgaline(x1, y1, x2, y2, n);
  27.                 int    x1, y1, x2, y2;    /* pixel co-ords */
  28.                 int    n;        /* color */
  29.  
  30.             no checking on endpoints!
  31.  
  32.     Adapted from Richard Wilton's code (PC and PS/2 Video Systems).
  33.     Modified to use VGA X mode
  34.     Call setup_hdwe()  before drawing groups of lines
  35.  
  36.         $
  37.  
  38.  
  39.  
  40.         .MODEL large
  41.         .CODE
  42.  
  43.         extrn _dpaddr
  44.  
  45. BytesPerLine    EQU        80
  46.  
  47. egapaddr    PROC    far
  48.  
  49.         mov    cl,bl
  50.         push    dx
  51.  
  52.         mov    dx,BytesPerLine
  53.         mul    dx
  54.  
  55.         pop    dx
  56.         shr    bx,1
  57.         shr    bx,1
  58.         add    bx,ax
  59.         add    bx,word ptr ds:_dpaddr
  60.  
  61.         and    cl,3
  62.           ;    xor    cl,3
  63.         mov    al,1
  64.         ret
  65.  
  66. egapaddr    endp
  67.  
  68.  
  69.  
  70. ; Stack frame addressing - LARGE CODE MODEL
  71.  
  72. ARGx1        EQU    word ptr [bp+6]
  73. ARGy1        EQU    word ptr [bp+8]
  74. ARGx2        EQU    word ptr [bp+10]
  75. ARGy2        EQU    word ptr [bp+12]
  76. ARGn        EQU    byte ptr [bp+14]
  77.  
  78. VARvertincr    EQU    word ptr [bp-6]
  79. VARincr1    EQU    word ptr [bp-8]
  80. VARincr2    EQU    word ptr [bp-10]
  81. VARroutine    EQU    word ptr [bp-12]
  82.  
  83. ByteOffsetShift    EQU    2
  84. RMWbits        EQU    0
  85.  
  86.         PUBLIC    _vgaline
  87.  
  88.  
  89. _vgaline    PROC    far
  90.         .386
  91.  
  92.         push    bp        ; Set up stack frame
  93.         mov    bp,sp
  94.         sub    sp,14
  95.         push    si
  96.         push    di
  97.  
  98. ; set color
  99.  
  100.         mov        ax,0a000h
  101.         mov        es,ax
  102.  
  103.         mov    bl,ARGn
  104.         mov    bh,0ffh
  105.         mov    al,es:[bx]
  106.  
  107.         mov    dx,03C5H    ; setup for plane mask access
  108.  
  109. ; check for vertical line
  110.  
  111.         mov    si,BytesPerLine
  112.         mov    cx,ARGx2
  113.         sub    cx,ARGx1
  114.         jz    VertLine
  115.  
  116. ; force x1 < x2
  117.  
  118.         jns    L01
  119.  
  120.         neg    cx
  121.  
  122.         mov    bx,ARGx2
  123.         xchg    bx,ARGx1
  124.         mov    ARGx2,bx
  125.  
  126.         mov    bx,ARGy2
  127.         xchg    bx,ARGy1
  128.         mov    ARGy2,bx
  129.  
  130. ; calc dy = abs(y2 - y1)
  131.  
  132. L01:
  133.         mov    bx,ARGy2
  134.         sub    bx,ARGy1
  135.         jz    HorizLine
  136.         jns    L03
  137.  
  138.         neg    bx
  139.         neg    si
  140.  
  141. ; select appropriate routine for slope of line
  142.  
  143. L03:
  144.         mov    VARvertincr,si
  145.         mov    VARroutine,offset LoSlopeLine
  146.         cmp    bx,cx
  147.         jle    L04
  148.         mov    VARroutine,offset HiSlopeLine
  149.         xchg    bx,cx
  150.  
  151. ; calc initial decision variable and increments
  152.  
  153. L04:
  154.         shl    bx,1
  155.         mov    VARincr1,bx
  156.         sub    bx,cx
  157.         mov    si,bx
  158.         sub    bx,cx
  159.         mov    VARincr2,bx
  160.  
  161. ; calc first pixel address
  162.  
  163.         push    cx
  164.         mov    ax,ARGy1
  165.         mov    bx,ARGx1
  166.         call    egapaddr
  167.         mov    di,bx
  168.         shl    al,cl
  169.         mov    ah,al        ; duplicate nybble
  170.         shl    al,4
  171.         add    al,ah
  172.         mov    bl,al
  173.         pop    cx
  174.         inc    cx
  175.         jmp    VARroutine
  176.  
  177. ; routine for verticle lines
  178.  
  179. VertLine:
  180.         mov    ax,ARGy1
  181.         mov    bx,ARGy2
  182.         mov    cx,bx
  183.         sub    cx,ax
  184.         jge    L31
  185.         neg    cx
  186.         mov    ax,bx
  187.  
  188. L31:
  189.         inc    cx
  190.         mov    bx,ARGx1
  191.         push    cx
  192.         call    egapaddr
  193.  
  194.         shl    al,cl
  195.         out    dx,al
  196.         pop    cx
  197.  
  198. ; draw the line
  199.  
  200. L32:
  201.         mov    es:[bx],ah
  202.         add    bx,si
  203.         loop    L32
  204.         jmp    Lexit
  205.  
  206. ; routine for horizontal line
  207.  
  208. HorizLine:
  209.         push    ds
  210.  
  211.         mov    ax,ARGy1
  212.         mov    bx,ARGx1
  213.         call    egapaddr
  214.         mov    di,bx
  215.         mov    dl,0ffh
  216.         shl    dl,cl
  217.  
  218.         mov    cx,ARGx2
  219.         and    cl,3
  220.         mov    dh,0feH
  221.         shl    dh,cl
  222.         not    dh
  223.  
  224. ; determine byte offset of first and last pixel in line
  225.  
  226.         mov    ax,ARGx2
  227.         mov    bx,ARGx1
  228.         mov    cl,ByteOffsetShift
  229.  
  230.         shr    ax,cl
  231.         shr    bx,cl
  232.         mov    cx,ax
  233.         sub    cx,bx
  234.  
  235.         mov    ax,dx
  236.         mov    dx,03c5h
  237.  
  238. ; set pixels in leftmost byte of line
  239.  
  240.         or    cx,cx
  241.         jnz    L42
  242.         and    ah,al
  243.         jmp    short L44
  244.  
  245. L42:
  246.         out     dx,al
  247.         stosb
  248.         dec    cx
  249.  
  250. ; draw remainder of the line
  251.  
  252. L43:
  253.         mov    al,0FFH
  254.         out    dx,al
  255.         rep    stosb
  256.  
  257. ; set pixels in rightmost byte of line
  258.  
  259. L44:
  260.         mov    al,ah
  261.         out    dx,al
  262.         mov     es:[di],bl
  263.         pop    ds
  264.         jmp    short Lexit
  265.  
  266.  
  267. ; routine for dy >= dx (slope <= 1)
  268.  
  269. LoSlopeLine:
  270.  
  271. L10:
  272.         mov    al,bl
  273.  
  274. L11:
  275.         or    al,bl
  276.         rol    bl,1
  277.         jc    L14
  278.  
  279. ; bit mask not shifted out
  280.  
  281.         or    si,si
  282.         jns    L12
  283.         add    si,VARincr1
  284.         loop    L11
  285.  
  286.         out    dx,al
  287.         mov    es:[di],ah
  288.         jmp    short Lexit
  289.  
  290. L12:
  291.         add    si,VARincr2
  292.         out    dx,al
  293.         mov    es:[di],ah
  294.         add    di,VARvertincr
  295.         loop    L10
  296.         jmp    short Lexit
  297.  
  298. ; bit mask shifted out
  299.  
  300. L14:            out    dx,al
  301.         stosb
  302.         or    si,si
  303.         jns    L15
  304.         add    si,VARincr1
  305.         loop    L10
  306.         jmp    short Lexit
  307.  
  308. L15:
  309.         add    si,VARincr2
  310.         add    di,VARvertincr
  311.         loop    L10
  312.         jmp    short Lexit
  313.  
  314.  
  315.  
  316. ; routine for dy > dx (slope > 1)
  317.  
  318. HiSlopeLine:
  319.         mov    bx,VARvertincr
  320.  
  321. L21:            out    dx,al
  322.         mov    es:[di],ah
  323.         add    di,bx
  324.  
  325. L22:
  326.         or    si,si
  327.         jns    L23
  328.  
  329.         add    si,VARincr1
  330.         loop    L21
  331.         jmp    short Lexit
  332.  
  333. L23:
  334.         add    si,VARincr2
  335.         rol    al,1
  336.         adc    di,0
  337. lx21:        loop    L21
  338.  
  339. ; return to caller
  340.  
  341. Lexit:
  342.         pop    di
  343.         pop    si
  344.         mov    sp,bp
  345.         pop    bp
  346.         ret
  347.  
  348. _vgaline    endp
  349.  
  350.  
  351.  
  352.  
  353.    ;
  354.    ;    int clipper (lpoints far *lp)
  355.    ;
  356.    ;  /* returns 0 if unclipped, 1 if clipped, and -1 if invisible */
  357.    ;
  358.    ;  Improved assembly version of Sutherland-Cohen line clipper
  359.    ;  Much more optimized than C version, and knows when to
  360.    ;  stop clipping!
  361.    ;
  362.  
  363.     PUBLIC    _clipper
  364.  
  365. x1    EQU    word ptr es:[bx]     ; elements in point array
  366. y1    EQU    word ptr es:[bx+2]
  367. x2    EQU    word ptr es:[bx+4]
  368. y2    EQU    word ptr es:[bx+6]
  369.  
  370. left  equ 8                          ; clipping flag bits
  371. above equ 4
  372. right equ 2
  373. below equ 1
  374.  
  375.     EXTRN    _l_clip              ; clipping recangle (assumed in ds)
  376.     EXTRN    _r_clip
  377.     EXTRN    _t_clip
  378.     EXTRN    _b_clip
  379.  
  380.  
  381. _clipper    proc    far
  382.  
  383.     .386                ; required for jump length only
  384.  
  385.     push    bp
  386.     mov    bp,sp
  387.     dec    sp
  388.     dec    sp
  389.     push    si
  390.     push    di
  391.     les    bx,dword ptr [bp+6]     ; setup access to points
  392.  
  393.     xor    di,di            ; flag1 = 0
  394.  
  395.     mov    ax,x1
  396.     cmp    ax,word ptr ds:_l_clip  ; set flag bits based on pos'n
  397.     jge    short nleft1            ; for point 1
  398.     or    di,8
  399. nleft1:
  400.     cmp    ax,word ptr ds:_r_clip
  401.     jle    short nright1
  402.     or    di,2
  403. nright1:
  404.     mov    ax,y1
  405.     cmp    ax,word ptr ds:_t_clip
  406.     jge    short ntop1
  407.     or    di,4
  408. ntop1:
  409.     cmp    ax,word ptr ds:_b_clip
  410.     jle    short nbot1
  411.     or    di,1
  412. nbot1:
  413.     xor    si,si            ; flag2 = 0
  414.  
  415.     mov    ax,x2
  416.     cmp    ax,word ptr ds:_l_clip  ; set flag bits based on pos'n
  417.     jge    short nleft2            ; for point 2
  418.     or    si,8
  419. nleft2:
  420.     cmp    ax,word ptr ds:_r_clip
  421.     jle    short nright2
  422.     or    si,2
  423. nright2:
  424.     mov    ax,y2
  425.     cmp    ax,word ptr ds:_t_clip
  426.     jge    short ntop2
  427.     or    si,4
  428. ntop2:
  429.     cmp    ax,word ptr ds:_b_clip
  430.     jle    short nbot2
  431.     or    si,1
  432. nbot2:
  433.  
  434.     mov    ax,di            ; check if all inside rect
  435.     or    ax,si
  436.     jne    short not_in_box
  437.     xor    ax,ax                   ; return 0: not clipped
  438. rexit:
  439.     pop    di
  440.     pop    si                      ; early return
  441.     mov    sp,bp
  442.     pop    bp
  443.     ret
  444.  
  445. not_in_box:
  446.     test    di,si                   ; check if all out of rect
  447.     je    short needs_clipping
  448. diagerr:                                ; too many clipping (diagonal)
  449.     mov    ax,65535
  450.     jmp    rexit                   ; return -1 (out of window)
  451.  
  452. needs_clipping:                         ; gotta do some serious work...
  453.  
  454.     or    di,di            ; quick test if pt.1 OK
  455.     jne    clip1
  456.     jmp    do2
  457.  
  458. clip1:                   ; clipping point 1:
  459.  
  460.     test    di,8                    ; left flag?
  461.     je    short notleft1
  462.  
  463. doleft1:
  464.    ;
  465.    ;        lp->y1 += (long)(lp->y2-lp->y1)*(l_clip-lp->x1)/(lp->x2-lp->x1);
  466.    ;
  467.     mov    cx,x2                   ; denominator: 0?
  468.     sub    cx,x1
  469.     je    dontleft1
  470.  
  471.     mov    ax,y2
  472.     sub    ax,y1
  473.     mov    dx,word ptr ds:_l_clip
  474.     sub    dx,x1
  475.     imul    dx
  476.     idiv    cx
  477.     add    y1,ax
  478.  
  479. dontleft1:
  480.     mov    dx,word ptr ds:_l_clip           ; clip left
  481.     mov    x1,dx
  482.  
  483.     mov    ax,y1                   ; check if vert. clipping needed
  484.     cmp    ax,word ptr ds:_t_clip
  485.     jl    doabove1
  486.     cmp    ax,word ptr ds:_b_clip
  487.     jg    dobelow1
  488.     jmp    do2                     ; else check point 2
  489.  
  490. notleft1:
  491.     test    di,2            ; test if right needs clipping
  492.     je    notright1
  493.  
  494. doright1:
  495.    ;
  496.    ;       lp->y1 += (long)(lp->y2-lp->y1)*(r_clip-lp->x1)/(lp->x2-lp->x1);
  497.    ;
  498.     mov    cx,x2                   ; denominator: 0?
  499.     sub    cx,x1
  500.     je    dontright1
  501.  
  502.     mov    ax,y2
  503.     sub    ax,y1
  504.     mov    dx,word ptr ds:_r_clip
  505.     sub    dx,x1
  506.     imul    dx
  507.     idiv    cx
  508.     add    y1,ax
  509.  
  510. dontright1:
  511.     mov    dx,word ptr ds:_r_clip           ; clip right
  512.     mov    x1,dx
  513.  
  514.     mov    ax,y1
  515.     cmp    ax,word ptr ds:_t_clip  ; check if vert. clipping needed
  516.     jl    doabove1
  517.     cmp    ax,word ptr ds:_b_clip
  518.     jg    dobelow1
  519.     jmp    do2
  520.  
  521. notright1:
  522.     test    di,4            ; test if top clip needed
  523.     je    short notabove1
  524.  
  525. doabove1:
  526.    ;
  527.    ;     lp->x1 += (long)(lp->x2-lp->x1)*(t_clip-lp->y1)/(lp->y2-lp->y1);
  528.    ;
  529.     mov    cx,y2                   ; denominator: 0?
  530.     sub    cx,y1
  531.     je    dontabove1
  532.  
  533.     mov    ax,x2
  534.     sub    ax,x1
  535.     mov    dx,word ptr ds:_t_clip
  536.     sub    dx,y1
  537.     imul    dx
  538.     idiv    cx
  539.     add    x1,ax
  540.  
  541. dontabove1:
  542.     mov    dx,word ptr ds:_t_clip           ; clip top
  543.     mov    y1,dx
  544.  
  545.     mov    ax,x1
  546.     cmp    ax,word ptr ds:_l_clip  ; if hor. clip req, diagonal outside
  547.     jl    diagerr ; doleft1
  548.     cmp    ax,word ptr ds:_r_clip
  549.     jg    diagerr ;doright1
  550.     jmp    short do2
  551.  
  552. notabove1:
  553.     test    di,1            ; test if bottom needs clipping
  554.     je    short do2
  555.  
  556. dobelow1:
  557.    ;
  558.    ;       lp->x1 += (long)(lp->x2-lp->x1)*(b_clip-lp->y1)/(lp->y2-lp->y1);
  559.    ;
  560.     mov    cx,y2                   ; denominator: 0?
  561.     sub    cx,y1
  562.     je    dontbelow1
  563.  
  564.     mov    ax,x2
  565.     sub    ax,x1
  566.     mov    dx,word ptr ds:_b_clip
  567.     sub    dx,y1
  568.     imul    dx
  569.     idiv    cx
  570.     add    x1,ax
  571.  
  572. dontbelow1:
  573.     mov    dx,word ptr ds:_b_clip
  574.     mov    y1,dx
  575.  
  576.     mov    ax,x1
  577.     cmp    ax,word ptr ds:_l_clip
  578.     jl    diagerr ;oleft1
  579.     cmp    ax,word ptr ds:_r_clip
  580.     jg    diagerr ;doright1
  581.  
  582.  
  583.  
  584.  
  585. do2:
  586.     or    si,si        ; same deal for point 2
  587.     je    done2
  588.     test    si,8
  589.     je    short notleft2
  590.  
  591. doleft2:
  592.    ;
  593.    ;      lp->y2 += (long)(lp->y1-lp->y2)*(l_clip-lp->x2)/(lp->x1-lp->x2);
  594.    ;
  595.     mov    cx,x1                   ; denominator: 0?
  596.     sub    cx,x2
  597.     je    dontleft2
  598.  
  599.     mov    ax,y1
  600.     sub    ax,y2
  601.     mov    dx,word ptr ds:_l_clip
  602.     sub    dx,x2
  603.     imul    dx
  604.     idiv    cx
  605.     add    y2,ax
  606.  
  607. dontleft2:
  608.     mov    dx,word ptr ds:_l_clip
  609.     mov    x2,dx
  610.  
  611.     mov    ax,y2
  612.     cmp    ax,word ptr ds:_t_clip
  613.     jl    doabove2
  614.     cmp    ax,word ptr ds:_b_clip
  615.     jg    dobelow2
  616.     jmp    done2
  617.  
  618. notleft2:
  619.     test    si,2            ; test if right needs clipping
  620.     je    notright2
  621.  
  622. doright2:
  623.    ;
  624.    ;      lp->y2 += (long)(lp->y1-lp->y2)*(r_clip-lp->x2)/(lp->x1-lp->x2);
  625.    ;
  626.     mov    cx,x1                   ; denominator: 0?
  627.     sub    cx,x2
  628.     je    dontright2
  629.  
  630.     mov    ax,y1
  631.     sub    ax,y2
  632.     mov    dx,word ptr ds:_r_clip
  633.     sub    dx,x2
  634.     imul    dx
  635.     idiv    cx
  636.     add    y2,ax
  637.  
  638. dontright2:
  639.     mov    dx,word ptr ds:_r_clip
  640.     mov    x2,dx
  641.  
  642.     mov    ax,y2
  643.     cmp    ax,word ptr ds:_t_clip
  644.     jl    doabove2
  645.     cmp    ax,word ptr ds:_b_clip
  646.     jg    dobelow2
  647.     jmp    done2
  648.  
  649. notright2:
  650.     test    si,4            ; test if top clip needed
  651.     je    short notabove2
  652.  
  653. doabove2:
  654.    ;
  655.    ;      lp->x2 += (long)(lp->x1-lp->x2)*(t_clip-lp->y2)/(lp->y1-lp->y2);
  656.    ;
  657.     mov    cx,y1                   ; denominator: 0?
  658.     sub    cx,y2
  659.     je    dontabove2
  660.  
  661.     mov    ax,x1
  662.     sub    ax,x2
  663.     mov    dx,word ptr ds:_t_clip
  664.     sub    dx,y2
  665.     imul    dx
  666.     idiv    cx
  667.     add    x2,ax
  668.  
  669. dontabove2:
  670.     mov    dx,word ptr ds:_t_clip
  671.     mov    y2,dx
  672.  
  673.     mov    ax,x2
  674.     cmp    ax,word ptr ds:_l_clip
  675.     jl    diagerr ;doleft2
  676.     cmp    ax,word ptr ds:_r_clip
  677.     jg    diagerr ;doright2
  678.     jmp    short done2
  679.  
  680. notabove2:
  681.     test    si,1            ; test if bottom needs clipping
  682.     je    short done2
  683.  
  684. dobelow2:
  685.    ;
  686.    ;      lp->x2 += (long)(lp->x1-lp->x2)*(b_clip-lp->y2)/(lp->y1-lp->y2);
  687.    ;
  688.     mov    cx,y1                   ; denominator: 0?
  689.     sub    cx,y2
  690.     je    dontbelow2
  691.  
  692.     mov    ax,x1
  693.     sub    ax,x2
  694.     mov    dx,word ptr ds:_b_clip
  695.     sub    dx,y2
  696.     imul    dx
  697.     idiv    cx
  698.     add    x2,ax
  699.  
  700. dontbelow2:
  701.     mov    dx,word ptr ds:_b_clip
  702.     mov    y2,dx
  703.  
  704.     mov    ax,x2
  705.     cmp    ax,word ptr ds:_l_clip
  706.     jl    diagerr ;doleft2
  707.     cmp    ax,word ptr ds:_r_clip
  708.     jg    diagerr ;doright2
  709.  
  710. done2:            ; finished point 2
  711.     mov    ax,1    ; return 1 for successful clipping
  712.     pop    di
  713.     pop    si
  714.     mov    sp,bp
  715.     pop    bp
  716.     ret
  717.  
  718. _clipper    endp
  719.  
  720.  
  721.     end